home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / x86 / include / asm / xen / hypercall.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  14.8 KB  |  528 lines

  1. /******************************************************************************
  2.  * hypercall.h
  3.  *
  4.  * Linux-specific hypervisor handling.
  5.  *
  6.  * Copyright (c) 2002-2004, K A Fraser
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License version 2
  10.  * as published by the Free Software Foundation; or, when distributed
  11.  * separately from the Linux kernel or incorporated into other
  12.  * software packages, subject to the following license:
  13.  *
  14.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  15.  * of this source file (the "Software"), to deal in the Software without
  16.  * restriction, including without limitation the rights to use, copy, modify,
  17.  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
  18.  * and to permit persons to whom the Software is furnished to do so, subject to
  19.  * the following conditions:
  20.  *
  21.  * The above copyright notice and this permission notice shall be included in
  22.  * all copies or substantial portions of the Software.
  23.  *
  24.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  27.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  28.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  29.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  30.  * IN THE SOFTWARE.
  31.  */
  32.  
  33. #ifndef _ASM_X86_XEN_HYPERCALL_H
  34. #define _ASM_X86_XEN_HYPERCALL_H
  35.  
  36. #include <linux/errno.h>
  37. #include <linux/string.h>
  38.  
  39. #include <xen/interface/xen.h>
  40. #include <xen/interface/sched.h>
  41. #include <xen/interface/physdev.h>
  42.  
  43. /*
  44.  * The hypercall asms have to meet several constraints:
  45.  * - Work on 32- and 64-bit.
  46.  *    The two architectures put their arguments in different sets of
  47.  *    registers.
  48.  *
  49.  * - Work around asm syntax quirks
  50.  *    It isn't possible to specify one of the rNN registers in a
  51.  *    constraint, so we use explicit register variables to get the
  52.  *    args into the right place.
  53.  *
  54.  * - Mark all registers as potentially clobbered
  55.  *    Even unused parameters can be clobbered by the hypervisor, so we
  56.  *    need to make sure gcc knows it.
  57.  *
  58.  * - Avoid compiler bugs.
  59.  *    This is the tricky part.  Because x86_32 has such a constrained
  60.  *    register set, gcc versions below 4.3 have trouble generating
  61.  *    code when all the arg registers and memory are trashed by the
  62.  *    asm.  There are syntactically simpler ways of achieving the
  63.  *    semantics below, but they cause the compiler to crash.
  64.  *
  65.  *    The only combination I found which works is:
  66.  *     - assign the __argX variables first
  67.  *     - list all actually used parameters as "+r" (__argX)
  68.  *     - clobber the rest
  69.  *
  70.  * The result certainly isn't pretty, and it really shows up cpp's
  71.  * weakness as as macro language.  Sorry.  (But let's just give thanks
  72.  * there aren't more than 5 arguments...)
  73.  */
  74.  
  75. extern struct { char _entry[32]; } hypercall_page[];
  76.  
  77. #define __HYPERCALL        "call hypercall_page+%c[offset]"
  78. #define __HYPERCALL_ENTRY(x)                        \
  79.     [offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
  80.  
  81. #ifdef CONFIG_X86_32
  82. #define __HYPERCALL_RETREG    "eax"
  83. #define __HYPERCALL_ARG1REG    "ebx"
  84. #define __HYPERCALL_ARG2REG    "ecx"
  85. #define __HYPERCALL_ARG3REG    "edx"
  86. #define __HYPERCALL_ARG4REG    "esi"
  87. #define __HYPERCALL_ARG5REG    "edi"
  88. #else
  89. #define __HYPERCALL_RETREG    "rax"
  90. #define __HYPERCALL_ARG1REG    "rdi"
  91. #define __HYPERCALL_ARG2REG    "rsi"
  92. #define __HYPERCALL_ARG3REG    "rdx"
  93. #define __HYPERCALL_ARG4REG    "r10"
  94. #define __HYPERCALL_ARG5REG    "r8"
  95. #endif
  96.  
  97. #define __HYPERCALL_DECLS                        \
  98.     register unsigned long __res  asm(__HYPERCALL_RETREG);        \
  99.     register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
  100.     register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
  101.     register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
  102.     register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
  103.     register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
  104.  
  105. #define __HYPERCALL_0PARAM    "=r" (__res)
  106. #define __HYPERCALL_1PARAM    __HYPERCALL_0PARAM, "+r" (__arg1)
  107. #define __HYPERCALL_2PARAM    __HYPERCALL_1PARAM, "+r" (__arg2)
  108. #define __HYPERCALL_3PARAM    __HYPERCALL_2PARAM, "+r" (__arg3)
  109. #define __HYPERCALL_4PARAM    __HYPERCALL_3PARAM, "+r" (__arg4)
  110. #define __HYPERCALL_5PARAM    __HYPERCALL_4PARAM, "+r" (__arg5)
  111.  
  112. #define __HYPERCALL_0ARG()
  113. #define __HYPERCALL_1ARG(a1)                        \
  114.     __HYPERCALL_0ARG()        __arg1 = (unsigned long)(a1);
  115. #define __HYPERCALL_2ARG(a1,a2)                        \
  116.     __HYPERCALL_1ARG(a1)        __arg2 = (unsigned long)(a2);
  117. #define __HYPERCALL_3ARG(a1,a2,a3)                    \
  118.     __HYPERCALL_2ARG(a1,a2)        __arg3 = (unsigned long)(a3);
  119. #define __HYPERCALL_4ARG(a1,a2,a3,a4)                    \
  120.     __HYPERCALL_3ARG(a1,a2,a3)    __arg4 = (unsigned long)(a4);
  121. #define __HYPERCALL_5ARG(a1,a2,a3,a4,a5)                \
  122.     __HYPERCALL_4ARG(a1,a2,a3,a4)    __arg5 = (unsigned long)(a5);
  123.  
  124. #define __HYPERCALL_CLOBBER5    "memory"
  125. #define __HYPERCALL_CLOBBER4    __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
  126. #define __HYPERCALL_CLOBBER3    __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
  127. #define __HYPERCALL_CLOBBER2    __HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
  128. #define __HYPERCALL_CLOBBER1    __HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
  129. #define __HYPERCALL_CLOBBER0    __HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
  130.  
  131. #define _hypercall0(type, name)                        \
  132. ({                                    \
  133.     __HYPERCALL_DECLS;                        \
  134.     __HYPERCALL_0ARG();                        \
  135.     asm volatile (__HYPERCALL                    \
  136.               : __HYPERCALL_0PARAM                \
  137.               : __HYPERCALL_ENTRY(name)                \
  138.               : __HYPERCALL_CLOBBER0);                \
  139.     (type)__res;                            \
  140. })
  141.  
  142. #define _hypercall1(type, name, a1)                    \
  143. ({                                    \
  144.     __HYPERCALL_DECLS;                        \
  145.     __HYPERCALL_1ARG(a1);                        \
  146.     asm volatile (__HYPERCALL                    \
  147.               : __HYPERCALL_1PARAM                \
  148.               : __HYPERCALL_ENTRY(name)                \
  149.               : __HYPERCALL_CLOBBER1);                \
  150.     (type)__res;                            \
  151. })
  152.  
  153. #define _hypercall2(type, name, a1, a2)                    \
  154. ({                                    \
  155.     __HYPERCALL_DECLS;                        \
  156.     __HYPERCALL_2ARG(a1, a2);                    \
  157.     asm volatile (__HYPERCALL                    \
  158.               : __HYPERCALL_2PARAM                \
  159.               : __HYPERCALL_ENTRY(name)                \
  160.               : __HYPERCALL_CLOBBER2);                \
  161.     (type)__res;                            \
  162. })
  163.  
  164. #define _hypercall3(type, name, a1, a2, a3)                \
  165. ({                                    \
  166.     __HYPERCALL_DECLS;                        \
  167.     __HYPERCALL_3ARG(a1, a2, a3);                    \
  168.     asm volatile (__HYPERCALL                    \
  169.               : __HYPERCALL_3PARAM                \
  170.               : __HYPERCALL_ENTRY(name)                \
  171.               : __HYPERCALL_CLOBBER3);                \
  172.     (type)__res;                            \
  173. })
  174.  
  175. #define _hypercall4(type, name, a1, a2, a3, a4)                \
  176. ({                                    \
  177.     __HYPERCALL_DECLS;                        \
  178.     __HYPERCALL_4ARG(a1, a2, a3, a4);                \
  179.     asm volatile (__HYPERCALL                    \
  180.               : __HYPERCALL_4PARAM                \
  181.               : __HYPERCALL_ENTRY(name)                \
  182.               : __HYPERCALL_CLOBBER4);                \
  183.     (type)__res;                            \
  184. })
  185.  
  186. #define _hypercall5(type, name, a1, a2, a3, a4, a5)            \
  187. ({                                    \
  188.     __HYPERCALL_DECLS;                        \
  189.     __HYPERCALL_5ARG(a1, a2, a3, a4, a5);                \
  190.     asm volatile (__HYPERCALL                    \
  191.               : __HYPERCALL_5PARAM                \
  192.               : __HYPERCALL_ENTRY(name)                \
  193.               : __HYPERCALL_CLOBBER5);                \
  194.     (type)__res;                            \
  195. })
  196.  
  197. static inline int
  198. HYPERVISOR_set_trap_table(struct trap_info *table)
  199. {
  200.     return _hypercall1(int, set_trap_table, table);
  201. }
  202.  
  203. static inline int
  204. HYPERVISOR_mmu_update(struct mmu_update *req, int count,
  205.               int *success_count, domid_t domid)
  206. {
  207.     return _hypercall4(int, mmu_update, req, count, success_count, domid);
  208. }
  209.  
  210. static inline int
  211. HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
  212.              int *success_count, domid_t domid)
  213. {
  214.     return _hypercall4(int, mmuext_op, op, count, success_count, domid);
  215. }
  216.  
  217. static inline int
  218. HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
  219. {
  220.     return _hypercall2(int, set_gdt, frame_list, entries);
  221. }
  222.  
  223. static inline int
  224. HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
  225. {
  226.     return _hypercall2(int, stack_switch, ss, esp);
  227. }
  228.  
  229. #ifdef CONFIG_X86_32
  230. static inline int
  231. HYPERVISOR_set_callbacks(unsigned long event_selector,
  232.              unsigned long event_address,
  233.              unsigned long failsafe_selector,
  234.              unsigned long failsafe_address)
  235. {
  236.     return _hypercall4(int, set_callbacks,
  237.                event_selector, event_address,
  238.                failsafe_selector, failsafe_address);
  239. }
  240. #else  /* CONFIG_X86_64 */
  241. static inline int
  242. HYPERVISOR_set_callbacks(unsigned long event_address,
  243.             unsigned long failsafe_address,
  244.             unsigned long syscall_address)
  245. {
  246.     return _hypercall3(int, set_callbacks,
  247.                event_address, failsafe_address,
  248.                syscall_address);
  249. }
  250. #endif  /* CONFIG_X86_{32,64} */
  251.  
  252. static inline int
  253. HYPERVISOR_callback_op(int cmd, void *arg)
  254. {
  255.     return _hypercall2(int, callback_op, cmd, arg);
  256. }
  257.  
  258. static inline int
  259. HYPERVISOR_fpu_taskswitch(int set)
  260. {
  261.     return _hypercall1(int, fpu_taskswitch, set);
  262. }
  263.  
  264. static inline int
  265. HYPERVISOR_sched_op(int cmd, void *arg)
  266. {
  267.     return _hypercall2(int, sched_op_new, cmd, arg);
  268. }
  269.  
  270. static inline long
  271. HYPERVISOR_set_timer_op(u64 timeout)
  272. {
  273.     unsigned long timeout_hi = (unsigned long)(timeout>>32);
  274.     unsigned long timeout_lo = (unsigned long)timeout;
  275.     return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
  276. }
  277.  
  278. static inline int
  279. HYPERVISOR_set_debugreg(int reg, unsigned long value)
  280. {
  281.     return _hypercall2(int, set_debugreg, reg, value);
  282. }
  283.  
  284. static inline unsigned long
  285. HYPERVISOR_get_debugreg(int reg)
  286. {
  287.     return _hypercall1(unsigned long, get_debugreg, reg);
  288. }
  289.  
  290. static inline int
  291. HYPERVISOR_update_descriptor(u64 ma, u64 desc)
  292. {
  293.     return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
  294. }
  295.  
  296. static inline int
  297. HYPERVISOR_memory_op(unsigned int cmd, void *arg)
  298. {
  299.     return _hypercall2(int, memory_op, cmd, arg);
  300. }
  301.  
  302. static inline int
  303. HYPERVISOR_multicall(void *call_list, int nr_calls)
  304. {
  305.     return _hypercall2(int, multicall, call_list, nr_calls);
  306. }
  307.  
  308. static inline int
  309. HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
  310.                  unsigned long flags)
  311. {
  312.     if (sizeof(new_val) == sizeof(long))
  313.         return _hypercall3(int, update_va_mapping, va,
  314.                    new_val.pte, flags);
  315.     else
  316.         return _hypercall4(int, update_va_mapping, va,
  317.                    new_val.pte, new_val.pte >> 32, flags);
  318. }
  319.  
  320. static inline int
  321. HYPERVISOR_event_channel_op(int cmd, void *arg)
  322. {
  323.     int rc = _hypercall2(int, event_channel_op, cmd, arg);
  324.     if (unlikely(rc == -ENOSYS)) {
  325.         struct evtchn_op op;
  326.         op.cmd = cmd;
  327.         memcpy(&op.u, arg, sizeof(op.u));
  328.         rc = _hypercall1(int, event_channel_op_compat, &op);
  329.         memcpy(arg, &op.u, sizeof(op.u));
  330.     }
  331.     return rc;
  332. }
  333.  
  334. static inline int
  335. HYPERVISOR_xen_version(int cmd, void *arg)
  336. {
  337.     return _hypercall2(int, xen_version, cmd, arg);
  338. }
  339.  
  340. static inline int
  341. HYPERVISOR_console_io(int cmd, int count, char *str)
  342. {
  343.     return _hypercall3(int, console_io, cmd, count, str);
  344. }
  345.  
  346. static inline int
  347. HYPERVISOR_physdev_op(int cmd, void *arg)
  348. {
  349.     int rc = _hypercall2(int, physdev_op, cmd, arg);
  350.     if (unlikely(rc == -ENOSYS)) {
  351.         struct physdev_op op;
  352.         op.cmd = cmd;
  353.         memcpy(&op.u, arg, sizeof(op.u));
  354.         rc = _hypercall1(int, physdev_op_compat, &op);
  355.         memcpy(arg, &op.u, sizeof(op.u));
  356.     }
  357.     return rc;
  358. }
  359.  
  360. static inline int
  361. HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
  362. {
  363.     return _hypercall3(int, grant_table_op, cmd, uop, count);
  364. }
  365.  
  366. static inline int
  367. HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
  368.                      unsigned long flags, domid_t domid)
  369. {
  370.     if (sizeof(new_val) == sizeof(long))
  371.         return _hypercall4(int, update_va_mapping_otherdomain, va,
  372.                    new_val.pte, flags, domid);
  373.     else
  374.         return _hypercall5(int, update_va_mapping_otherdomain, va,
  375.                    new_val.pte, new_val.pte >> 32,
  376.                    flags, domid);
  377. }
  378.  
  379. static inline int
  380. HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
  381. {
  382.     return _hypercall2(int, vm_assist, cmd, type);
  383. }
  384.  
  385. static inline int
  386. HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
  387. {
  388.     return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
  389. }
  390.  
  391. #ifdef CONFIG_X86_64
  392. static inline int
  393. HYPERVISOR_set_segment_base(int reg, unsigned long value)
  394. {
  395.     return _hypercall2(int, set_segment_base, reg, value);
  396. }
  397. #endif
  398.  
  399. static inline int
  400. HYPERVISOR_suspend(unsigned long srec)
  401. {
  402.     return _hypercall3(int, sched_op, SCHEDOP_shutdown,
  403.                SHUTDOWN_suspend, srec);
  404. }
  405.  
  406. static inline int
  407. HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
  408. {
  409.     return _hypercall2(int, nmi_op, op, arg);
  410. }
  411.  
  412. static inline void
  413. MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
  414. {
  415.     mcl->op = __HYPERVISOR_fpu_taskswitch;
  416.     mcl->args[0] = set;
  417. }
  418.  
  419. static inline void
  420. MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
  421.             pte_t new_val, unsigned long flags)
  422. {
  423.     mcl->op = __HYPERVISOR_update_va_mapping;
  424.     mcl->args[0] = va;
  425.     if (sizeof(new_val) == sizeof(long)) {
  426.         mcl->args[1] = new_val.pte;
  427.         mcl->args[2] = flags;
  428.     } else {
  429.         mcl->args[1] = new_val.pte;
  430.         mcl->args[2] = new_val.pte >> 32;
  431.         mcl->args[3] = flags;
  432.     }
  433. }
  434.  
  435. static inline void
  436. MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
  437.              void *uop, unsigned int count)
  438. {
  439.     mcl->op = __HYPERVISOR_grant_table_op;
  440.     mcl->args[0] = cmd;
  441.     mcl->args[1] = (unsigned long)uop;
  442.     mcl->args[2] = count;
  443. }
  444.  
  445. static inline void
  446. MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
  447.                     pte_t new_val, unsigned long flags,
  448.                     domid_t domid)
  449. {
  450.     mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
  451.     mcl->args[0] = va;
  452.     if (sizeof(new_val) == sizeof(long)) {
  453.         mcl->args[1] = new_val.pte;
  454.         mcl->args[2] = flags;
  455.         mcl->args[3] = domid;
  456.     } else {
  457.         mcl->args[1] = new_val.pte;
  458.         mcl->args[2] = new_val.pte >> 32;
  459.         mcl->args[3] = flags;
  460.         mcl->args[4] = domid;
  461.     }
  462. }
  463.  
  464. static inline void
  465. MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
  466.             struct desc_struct desc)
  467. {
  468.     mcl->op = __HYPERVISOR_update_descriptor;
  469.     if (sizeof(maddr) == sizeof(long)) {
  470.         mcl->args[0] = maddr;
  471.         mcl->args[1] = *(unsigned long *)&desc;
  472.     } else {
  473.         mcl->args[0] = maddr;
  474.         mcl->args[1] = maddr >> 32;
  475.         mcl->args[2] = desc.a;
  476.         mcl->args[3] = desc.b;
  477.     }
  478. }
  479.  
  480. static inline void
  481. MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
  482. {
  483.     mcl->op = __HYPERVISOR_memory_op;
  484.     mcl->args[0] = cmd;
  485.     mcl->args[1] = (unsigned long)arg;
  486. }
  487.  
  488. static inline void
  489. MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
  490.          int count, int *success_count, domid_t domid)
  491. {
  492.     mcl->op = __HYPERVISOR_mmu_update;
  493.     mcl->args[0] = (unsigned long)req;
  494.     mcl->args[1] = count;
  495.     mcl->args[2] = (unsigned long)success_count;
  496.     mcl->args[3] = domid;
  497. }
  498.  
  499. static inline void
  500. MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
  501.         int *success_count, domid_t domid)
  502. {
  503.     mcl->op = __HYPERVISOR_mmuext_op;
  504.     mcl->args[0] = (unsigned long)op;
  505.     mcl->args[1] = count;
  506.     mcl->args[2] = (unsigned long)success_count;
  507.     mcl->args[3] = domid;
  508. }
  509.  
  510. static inline void
  511. MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
  512. {
  513.     mcl->op = __HYPERVISOR_set_gdt;
  514.     mcl->args[0] = (unsigned long)frames;
  515.     mcl->args[1] = entries;
  516. }
  517.  
  518. static inline void
  519. MULTI_stack_switch(struct multicall_entry *mcl,
  520.            unsigned long ss, unsigned long esp)
  521. {
  522.     mcl->op = __HYPERVISOR_stack_switch;
  523.     mcl->args[0] = ss;
  524.     mcl->args[1] = esp;
  525. }
  526.  
  527. #endif /* _ASM_X86_XEN_HYPERCALL_H */
  528.